package com.step.sprite;

import javax.microedition.khronos.opengles.GL10;

import com.step.Step;
import com.step.graphic.Texture;
import com.step.graphic.TextureRegion;
import com.step.math.Vector;
import com.step.mesh.Color;
import com.step.mesh.Mesh;
import com.step.mesh.buffer.CoordinateBuffer;

public abstract class Sprite {
	protected Vector position;	
	protected Vector scale;
	protected Vector rotation;
	private String name;
	private boolean isVisible = true;
	
	private Color defaultColor = new Color();
	private ShadeModel shadeModel = ShadeModel.SMOOTH;
	private RenderType renderType = RenderType.TRIANGLES;
	private float pointSize = 3f;
	private boolean usePointSmoothing = true;
	private float lineWidth = 1f;
	private boolean useLineSmoothing = true;	
	
	protected Mesh mesh;
	protected Texture texture;
	protected boolean animationEnable = false;
	protected IContainer parent;
	private boolean isBinded = false;
	
	public Sprite(Mesh mesh, Texture texture){
		this.mesh = mesh;
		this.texture = texture;
	}
	
	public Sprite(Mesh mesh, TextureRegion region){
		this(mesh, region.getTexture());
	}
	
	public void setRegion(TextureRegion region){
		Texture regionTexture = region.getTexture();
		
		if(!texture.equals(regionTexture)){
			changeTexture(regionTexture);
		}
		
		changeUv(region);
	}

	private void changeUv(TextureRegion region) {
		float u1 = region.getU1();
		float v1 = region.getV1();
		float u2 = region.getU2();
		float v2 = region.getV2();
		
		CoordinateBuffer uvBuffer = mesh.getUvBuffer();
		uvBuffer.set(0, u1, v2);
		uvBuffer.set(1, u2, v2);
		uvBuffer.set(2, u2, v1);
		uvBuffer.set(3, u1, v1);
	}
	
	public void dispose(){
		if(mesh != null) mesh.dispose();
		if(texture != null) texture.dispose();
	}
	
	public void draw(GL10 gl){
		draw(gl, renderType);
	}
	
	public void draw(GL10 gl,RenderType renderType){
		if(this.isVisible == false) return;
		if(this.mesh == null) return;
		Step.log("Sprite-纹理坐标："+mesh.hasUv()+", 纹理："+(texture != null));
		// 纹理
		if(mesh.hasUv() && texture != null){			
			if(isBinded == false) {
				gl.glEnable(GL10.GL_TEXTURE_2D);
				texture.bind();
				isBinded = true;				
			}
		}
		else{
			gl.glDisable(GL10.GL_TEXTURE_2D);
		}
		
		gl.glPushMatrix();
		// 平移、旋转、缩放
		transform(gl);
		// 网格
		mesh.render(gl, renderType);
		gl.glPopMatrix();
	}
	
	protected void transform(GL10 gl){		
		gl.glTranslatef(position.getX(), position.getY(), position.getZ());
		Step.log("Sprite-旋转:"+rotation.toString());
		if(rotation.getX() != 0) gl.glRotatef(rotation.getX(), 1, 0, 0);
		if(rotation.getY() != 0) gl.glRotatef(rotation.getY(), 0, 1, 0);
		if(rotation.getZ() != 0) gl.glRotatef(rotation.getZ(), 0, 0, 1);
		
		if(scale.getX() != 1 || scale.getY() != 1 || scale.getZ() != 1){
			if(scale.is2D()){
				gl.glScalef(scale.getX(), scale.getY(), 1);
			}
			else{
				gl.glScalef(scale.getX(), scale.getY(), scale.getZ());
			}
		}
	}

	public abstract boolean is2D();
	public abstract boolean is3D();
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public boolean isVisible() {
		return isVisible;
	}

	public void setVisible(boolean isVisible) {
		this.isVisible = isVisible;
	}

	public Color getDefaultColor() {
		return defaultColor;
	}

	public void setDefaultColor(Color defaultColor) {
		this.defaultColor = defaultColor;
	}

	public ShadeModel getShadeModel() {
		return shadeModel;
	}

	public void setShadeModel(ShadeModel shadeModel) {
		this.shadeModel = shadeModel;
	}

	public RenderType getRenderType() {
		return renderType;
	}

	public void setRenderType(RenderType renderType) {
		this.renderType = renderType;
	}

	public float getPointSize() {
		return pointSize;
	}

	public void setPointSize(float pointSize) {
		this.pointSize = pointSize;
	}

	public boolean isPointSmoothing() {
		return usePointSmoothing;
	}

	public void setPointSmoothing(boolean usePointSmoothing) {
		this.usePointSmoothing = usePointSmoothing;
	}

	public float getLineWidth() {
		return lineWidth;
	}

	public void setLineWidth(float lineWidth) {
		this.lineWidth = lineWidth;
	}

	public boolean isLineSmoothing() {
		return useLineSmoothing;
	}

	public void setLineSmoothing(boolean useLineSmoothing) {
		this.useLineSmoothing = useLineSmoothing;
	}

	public Mesh getMesh() {
		return mesh;
	}

	public void setMesh(Mesh mesh) {
		this.mesh = mesh;
	}

	public Texture getTexture() {
		return texture;
	}

	public void setTexture(Texture texture) {
		if(texture == this.texture) return;		
		changeTexture(texture);		
		changeUv(texture.getRegion());
	}

	private void changeTexture(Texture texture){
		this.texture = texture;
		this.isBinded = false;
	}
	public boolean isAnimationEnable() {
		return animationEnable;
	}

	public void setAnimationEnable(boolean animationEnable) {
		this.animationEnable = animationEnable;
	}

	public IContainer getParent() {
		return parent;
	}

	public void setParent(IContainer parent) {
		this.parent = parent;
	}
	
	public enum ShadeModel{
		SMOOTH (GL10.GL_SMOOTH),
		FLAT (GL10.GL_FLAT);
		
		private final int glConstant;
		
		private ShadeModel(int glConstant)	{
			this.glConstant = glConstant;
		}
		
		public int glConstant() {
			return glConstant;
		}
	}
	
	public enum RenderType{
		POINTS (GL10.GL_POINTS),
		LINES (GL10.GL_LINES),
		LINE_LOOP (GL10.GL_LINE_LOOP),
		LINE_STRIP (GL10.GL_LINE_STRIP),
		TRIANGLES (GL10.GL_TRIANGLES),
		TRIANGLE_STRIP (GL10.GL_TRIANGLE_STRIP),
		TRIANGLE_FAN (GL10.GL_TRIANGLE_FAN);
		
		private final int glValue;
		
		private RenderType(int glValue)	{
			this.glValue = glValue;
		}
		
		public int glValue(){
			return glValue;
		}
	}
}
